SwiftUI 如何监听 @State 变更
几种实现方式
import Combine
struct ObserveStateChange: View {
var body: some View {
VStack(spacing: 32) {
Solution1().padding().background(Color.red)
Solution2().padding().background(Color.yellow)
Solution3().padding().background(Color.green)
}
}
/// 1
struct Solution1: View {
@State var location: String = ""
var body: some View {
let binding = Binding<String>(get: {
self.location
}, set: {
self.location = $0
// do whatever you want here
print("Solution1 \($0)")
})
TextField("Search Location", text: binding)
}
}
/// 2
struct Solution2: View {
@State var location: String = ""
var body: some View {
TextField("Search Location", text: $location)
.onReceive(Just(location)) { print("Solution2 \($0)") }
}
}
/// 3
struct Solution3: View {
@State var location: String = ""
var body: some View {
TextField("Search Location", text: $location.onChange { print("Solution3 \($0)") })
}
}
/// 4
struct Solution4: View {
@State var location: String = ""
var body: some View {
TextField("Search Location", text: $location)
.onChange(of: location) {
print("Solution4 \($0)")
}
}
}
}
extension Binding {
func onChange(_ handler: @escaping (Value) -> Void) -> Binding<Value> {
Binding(
get: { self.wrappedValue },
set: { newValue in
self.wrappedValue = newValue
handler(newValue)
}
)
}
}
1⃣️使用定义一个 Binding 属性,通过 get 和 set 来变更 @State。
2⃣️通过 onReceive 监听 Just Publisher 包装 State 促发的事件
3⃣️通过拓展 Binding 添加一个方法实现方法一的类似实现,包裹一层 Binding 来将变更回调出去。
4⃣️iOS14 支持的新特性。
经过实践推荐使用3⃣️或者4⃣️。